Endianness (byte order)

  • Endianness defines how multi-byte values are laid out in memory—specifically, the order in which bytes are stored.

  • Endianness decides which byte goes at the lowest memory address.

  • It's about the BYTE  order, not the BIT  order inside the bytes.

    • Inside a single byte, the bit positions are fixed:

    bit index:  7 6 5 4 3 2 1 0
    value:      128 ...       1
    
    • That mapping (MSB ↔ bit 7, LSB ↔ bit 0) is unchanged regardless of endianness.

Little-endian (reversed byte order in memory / "little byte comes first")

  • Least significant byte stored first (lowest address)

  • Most systems today are little-endian.

value:     0x12345678
Address:   +0   +1   +2   +3
Memory:    78   56   34   12   (little-endian)
  • Used by:

    • x86 / x86-64

    • ARM (default today)

    • most modern systems

Why
  • Carry propagation naturally walks forward in memory.

  • A pointer to a larger integer can be reinterpreted as a smaller one without adjusting the address.

    • Example: reading a u8 from a u32* just reads the first byte (LSB).

  • Early CPUs like the Intel 8086 used little-endian.

    • Their internal design made it natural to fetch/store the low byte first.

    • Success of x86 cemented little-endian as the de facto standard.

  • Operations that grow precision (e.g. multi-precision arithmetic) can extend “forward” in memory.

    • Useful for things like bignum libraries.

  • The dominance of little-endian is mostly inertia:

    • x86 (little-endian) became ubiquitous in desktops/servers.

    • ARM defaults to little-endian in almost all modern systems.

    • Toolchains, file formats, and OS ecosystems followed.

Big-endian (same order you write numbers / "big byte comes first")

  • Most significant byte first

Value:     0x12345678
Address:   +0   +1   +2   +3
Memory:    12   34   56   78
  • Used by:

    • Networking protocols (e.g. TCP/IP)

    • older architectures (e.g., PowerPC in certain modes)

Why
  • Big-endian isn’t worse—just optimized for different priorities:

    • Memory layout matches human-readable order (easier debugging).

    • Network protocols standardized on it → “network byte order”.

    • Some architectures (older PowerPC, SPARC) favored it.

Examples

String8

  • Endianness only matters once you break 16-bit units into bytes. For 8-bit strings, there’s no ambiguity.

  • No endianness concerns here.

'o'  = 01101111 = 0x6F
'i'  = 01101001 = 0x69
null = 00000000 = 0x00
  • oi\0  in string8

"oi" → 01101111 01101001 00000000

String16

'o'  = 0x006F -> 0x6F00 (little-endian) / 0x006F (big-endian)
'i'  = 0x0069 -> 0x6900 (little-endian) / 0x0069 (big-endian)
null = 0x0000 -> 0x0000
  • oi\0  in little-endian

"oi" → 01101111 00000000 01101001 00000000 00000000 00000000
  • oi\0  in big-endian

"oi" → 00000000 01101111 00000000 01101001 00000000 00000000